<?php

namespace App\Services\Easywechat;

use App\Master\Framework\Extend\Module;
use EasyWeChat\Pay\Application;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;

class PayService extends EasyModule
{
    /**
     * @var Application
     */
    private Application $app;
    private array       $config;

    /**
     * 实例化
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     */
    public function __construct()
    {
        parent::__construct();
        // 微信开发配置
        $_table = "EasywechatConfig";
        $config = Cache::remember("PAY_SERVICE_{$_table}", $this->ttl, function () use ($_table) {
            $module = Module::_SetupModule($_table);
            $module = $module['pay'] ?? [];
            if (!empty($module['key_pem'])) {
                $file = fopen(__DIR__ . '/certs/sup/apiclient_key.pem', "w");
                fwrite($file, $module['key_pem']);
                fclose($file);
            }
            if (!empty($module['cert_pem'])) {
                $file = fopen(__DIR__ . '/certs/sup/apiclient_cert.pem', "w");
                fwrite($file, $module['cert_pem']);
                fclose($file);
            }
            return $module;
        });

        $config = [
            'app_id'        => $config['app_id'] ?? '',
            'mch_id'        => $config['mch_id'] ?? '',
            // 商户证书
            'private_key'   => __DIR__ . '/certs/sup/apiclient_key.pem',
            'certificate'   => __DIR__ . '/certs/sup/apiclient_cert.pem',
            // v2 API 秘钥
            'v2_secret_key' => $config['api_v2'] ?? '',
            'secret_key'    => $config['api_v3'] ?? '',
            /**
             * 接口请求相关配置，超时时间等，具体可用参数请参考：
             * https://github.com/symfony/symfony/blob/5.3/src/Symfony/Contracts/HttpClient/HttpClientInterface.php
             */
            'http'          => [
                'throw'   => true, // 状态码非 200、300 时是否抛出异常，默认为开启
                'timeout' => 5.0,
//                'base_uri' => 'https://api.mch.weixin.qq.com/', // 如果你在国外想要覆盖默认的 url 的时候才使用，根据不同的模块配置不同的 uri
            ],
        ];

        $this->config = $config;
        $this->app    = new Application($config);
    }

    public function app()
    {
        return $this->app;
    }

    /**
     * 统一下单
     *
     * @param string $openid
     * @param string $out_trade_no
     * @param int $fee
     * @param string $description
     * @param string $notify_url
     * @return bool
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \Exception
     */
    public function jsapi(string $openid, string $out_trade_no, int $fee = 0, string $description = '', string $notify_url = '')
    {
        $app = $this->app;

        $api = $app->getClient();

        $response = $api->postJson("v3/pay/transactions/jsapi", [
            'mchid'        => $this->config['mch_id'], // <---- 请修改为您的【子商户号/二级商户号】由微信支付生成并下发。
            "out_trade_no" => $out_trade_no,// 外部商户订单号
            "appid"        => $this->config['app_id'], // <---- 请修改为【子商户号/二级商户号】服务号的 appid
            "description"  => $description,
            "notify_url"   => $notify_url,// 回调地址
            "amount"       => [
                "total"    => $fee,
                "currency" => "CNY"
            ],
            "payer"        => [
                "openid" => $openid, // <---- 【用户子标识】 用户在子商户AppID下的唯一标识。若传sub_openid，那sub_appid必填。下单前需获取到用户的OpenID
            ]
        ])->throw(false);

        if (!$this->response($response)) {
            return false;
        }

        if (empty($this->data['prepay_id'])) {
            return false;
        }

        $appId      = $this->config['app_id'];
        $signType   = 'RSA'; // 默认RSA，v2要传MD5
        $utils      = $app->getUtils();
        $this->data = $utils->buildBridgeConfig($this->data['prepay_id'], $appId, $signType); // 返回数组

        return true;
    }

    /**
     * App下单
     * TODO 有待测试
     * @param string $out_trade_no
     * @param int $fee
     * @param string $description
     * @param string $notify_url
     * @return bool
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     */
    public function appPay(string $out_trade_no, int $fee = 0, string $description = '', string $notify_url = '')
    {
        $app = $this->app;

        $api = $app->getClient();

        $response = $api->postJson("v3/pay/transactions/app", [
            "appid"        => $this->config['app_id'], // <---- 请修改为【子商户号/二级商户号】服务号的 appid
            'mchid'        => $this->config['mch_id'], // <---- 请修改为您的【子商户号/二级商户号】由微信支付生成并下发。
            "description"  => $description,
            "out_trade_no" => $out_trade_no,// 外部商户订单号
            "notify_url"   => $notify_url,// 回调地址
            "amount"       => [
                "total"    => $fee,
                "currency" => "CNY"
            ]
        ])->throw(false);

        if (!$this->response($response)) {
            return false;
        }

        if (empty($this->data['prepay_id'])) {
            return false;
        }

        $appId      = $this->config['app_id'];
        $signType   = 'RSA'; // 默认RSA，v2要传MD5
        $utils      = $app->getUtils();
        $this->data = $utils->buildBridgeConfig($this->data['prepay_id'], $appId, $signType); // 返回数组

        return true;
    }

    /**
     * H5下单
     * TODO 有待完善
     * @param string $out_trade_no
     * @param int $fee
     * @param string $description
     * @param string $notify_url
     * @return bool
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     */
    public function h5Pay(string $out_trade_no, int $fee = 0, string $description = '', string $notify_url = '')
    {
        $app = $this->app;

        $api = $app->getClient();

        $response = $api->postJson("v3/pay/transactions/h5", [
            "appid"        => $this->config['app_id'], // <---- 请修改为【子商户号/二级商户号】服务号的 appid
            'mchid'        => $this->config['mch_id'], // <---- 请修改为您的【子商户号/二级商户号】由微信支付生成并下发。
            "description"  => $description,
            "out_trade_no" => $out_trade_no,// 外部商户订单号
            "notify_url"   => $notify_url,// 回调地址
            "amount"       => [
                "total"    => $fee,
                "currency" => "CNY"
            ],
            "scene_info" => [
                "payer_client_ip" => $_SERVER['HTTP_X_REAL_IP'] ?? Request::capture()->getClientIp(),
                ""
            ]
        ])->throw(false);

        if (!$this->response($response)) {
            return false;
        }

        if (empty($this->data['prepay_id'])) {
            return false;
        }

        $appId      = $this->config['app_id'];
        $signType   = 'RSA'; // 默认RSA，v2要传MD5
        $utils      = $app->getUtils();
        $this->data = $utils->buildBridgeConfig($this->data['prepay_id'], $appId, $signType); // 返回数组

        return true;
    }
}